﻿using System;
using System.Data.Entity;
using AdventureWorks.Entities;
using AdventureWorks.DAO;

namespace AdventureWorksData.DAO
{
	public sealed class UnitOfWork : IDisposable, IUnitOfWork
	{
		private Boolean _disposed;
		private readonly AdventureWorksContext _context;
		private GenericRepository<Customer> _customer;
		private GenericRepository<Address> _address;
		private GenericRepository<Product> _product;
        private GenericRepository<ProductModel> _productModels;
		private GenericRepository<ProductCategory> _productCategories;

		public UnitOfWork()
		{
			_context = new AdventureWorksContext();
		}

		public UnitOfWork(AdventureWorksContext context)
		{
			_context = context;
		}

		public IGenericRepository<Customer> Customers
		{
			get
			{
				var db = _context.Set<Customer>();
				return _customer ?? (_customer = new GenericRepository<Customer>(_context, db));
			}
		}

		public IGenericRepository<Address> Addresses
		{
			get
			{
				var db = _context.Set<Address>();
				return _address ?? (_address = new GenericRepository<Address>(_context, db));
			}
		}

		public IGenericRepository<Product> Products
		{
			get
			{
				var db = _context.Set<Product>();
				return _product ?? (_product = new GenericRepository<Product>(_context, db));
			}
		}

		public IGenericRepository<ProductModel> ProductModels
        {
            get
            {
				var db = _context.Set<ProductModel>();
            	return _productModels ?? (_productModels = new GenericRepository<ProductModel>(_context, db));
            }
        }

		public IGenericRepository<ProductCategory> ProductCategories
		{
			get
			{
				var db = _context.Set<ProductCategory>();

				return _productCategories ?? (_productCategories = new GenericRepository<ProductCategory>(_context, db));
			}
		}

		public void Save()
		{
			_context.SaveChanges();
		}

		private void Dispose(Boolean disposing)
		{
			if (_disposed)
			{
				if (disposing)
				{
					_context.Dispose();
				}
			}
			_disposed = true;
		}

		public void Dispose()
		{
			Dispose(true);
			GC.SuppressFinalize(this);
		}
    }
}
